<template>
    <div class="ip-input-container">
        <div class="ip-segment" v-for="(segment, index) in segments">
            <input type="text" maxlength="3" class="ip-segment-input" :value="segment"
                   v-on:keydown="onInputKeydown($event, index)"
                   v-on:input="onInput($event, index)">
            <i v-show="index != segments.length - 1">.</i>
        </div>
        <div class="ip-segment" v-show="isPortShow" style="width: 50px">
            <span>:</span>
            <input ref="portInput" type="text" maxlength="5" v-model="port" class="ip-segment-input" style="width: 40px"
                   v-on:keydown="onInputKeydown($event, 4)"
                   v-on:input="onPortInput">
        </div>
    </div>
</template>

<script>
    function getRange(el) {
        var cuRange;
        var tbRange;
        var headRange;
        var range;
        var dupRange;
        var ret = {};
        if (el.setSelectionRange) {
            // standard
            ret.begin = el.selectionStart;
            ret.end = el.selectionEnd;
            ret.result = el.value.substring(ret.begin, ret.end);
        } else if (document.selection) {
            // ie
            if (el.tagName.toLowerCase() === 'input') {
                cuRange = document.selection.createRange();
                tbRange = el.createTextRange();
                tbRange.collapse(true);
                tbRange.select();
                headRange = document.selection.createRange();
                headRange.setEndPoint('EndToEnd', cuRange);
                ret.begin = headRange.text.length - cuRange.text.length;
                ret.end = headRange.text.length;
                ret.result = cuRange.text;
                cuRange.select();
            } else if (el.tagName.toLowerCase() === 'textarea') {
                range = document.selection.createRange();
                dupRange = range.duplicate();
                dupRange.moveToElementText(el);
                dupRange.setEndPoint('EndToEnd', range);
                ret.begin = dupRange.text.length - range.text.length;
                ret.end = dupRange.text.length;
                ret.result = range.text;
            }
        }
        el.focus();
        return ret;
    }

    export default {
        name: "hr-vue-ip-input",
        props: {
            value: Object,
            showPort: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                segments: ['', '', '', ''],
                port: '',
            };
        },
        computed: {
            isPortShow: function () {
                let rst = this.value.port !== undefined
                return this.showPort || rst
            },
            ipData: function () {
                let data = {
                    ip: this.segments.join('.'),
                }
                if (this.isPortShow) {
                    data.port = this.port
                }
                return data
            },
            nums: function () {
                return this.isPortShow ? 4 : 3
            }
        },
        watch: {
            segments(segments) {
                this.$emit('input', this.ipData)
            },
            port(port) {
                this.$emit('input', this.ipData)
            },
            value(value) {
                if (value.ip != this.ipData.ip || value.port != this.ipData.port) {
                    this.sync(value)
                }
            }
        },
        methods: {
            onInputKeydown(event, index) {
                var keyCode = event.keyCode || event.which;
                var value = event.target.value;
                if (keyCode === 8 || keyCode === 37) {
                    // move the cursor to previous input if backspace and left arrow is pressed at the begin of one input
                    if ((value.length === 0 || getRange(event.target).end === 0) &&
                        index > 0) {
                        this.$el.getElementsByTagName('input')[index - 1].focus();
                        // When jump to pre input(enter "backspace"), thr cursor should in the end.
                        // before fix: 127.|0.0.0  =>   12|7.0.0.1
                        // after fix: 127.|0.0.0 = >   127|.0.0.0
                        // notes: "|" mean the cursor position.
                        event.preventDefault();
                    }
                } else if (keyCode === 39) {
                    if (getRange(event.target).end === value.length && index < this.nums) {
                        // move to cursor to the next input if right arrow is pressed at the end of one input
                        this.$el.getElementsByTagName('input')[index + 1].focus();
                    }
                }
            },
            onInput(event, index) {
                var value = event.target.value;
                event.target.value = this.segments[index];
                var segment = Number(value);
                if (isNaN(segment)) {
                    return;
                } else if (value === '') {
                    this.segments.splice(index, 1, '');
                } else if (segment > 255 || segment < 0) {
                    // set the segment to 255 if out of ip range
                    this.segments.splice(index, 1, 255);
                } else {
                    this.segments.splice(index, 1, segment);
                }
                // jump to next input
                if (value.length === 3 && index < 3 || value[value.length - 1] === '.') {
                    this.$el.getElementsByTagName('input')[index + 1].focus();
                }

                if (this.isPortShow && value.length === 3 && index == 3) {
                    this.$refs['portInput'].focus()
                }
            },
            onPortInput() {
                if(this.port < 0 || this.port > 65536){
                    this.port = '8080'
                }
            },
            sync(data) {
                this.port = data.port
                let ip = data.ip
                if(!ip || ip.trim() == ''){
                    this.segments = ['','','','']
                }else {
                    if (ip && ip.indexOf('.') !== -1) {
                        ip.split('.').map((segment, index) => {
                            if (isNaN(segment) || segment < 0 || segment > 255) {
                                segment = 255;
                            }
                            this.segments.splice(index, 1, segment);
                            return segment;
                        });
                    }
                }
            }
        },
        mounted() {
            this.sync(this.value)
        }
    }
</script>

<style lang="sass-loader" scoped>
    .ip-input-container {
        display: inline-block;
        height: 28px;
        line-height: normal;
        border: 1px solid #ccc;
        box-sizing: border-box;
        background-color: #fff;
    }

    .ip-segment {
        display: inline-block;
        width: 39px;
        height: 26px;
        line-height: normal;

    input {
        width: 30px;
        height: 26px;
        line-height: normal;
        border: none;
        outline: none;
        text-align: center;
        text-indent: 0px;
        margin: 0px;
        padding: 0px;
        background-color: transparent;
    }

    i {
        display: inline-block;
        font-size: 18px;
    }

    }


</style>